<template>
  <ContentWrap>
    <div class="mx-auto">
      <!-- 头部导航栏 -->
      <div
        class="absolute top-0 left-0 right-0 h-50px bg-white border-bottom z-10 flex items-center px-20px"
      >
        <!-- 左侧标题 -->
        <div class="w-200px flex items-center overflow-hidden">
          <Icon icon="ep:arrow-left" class="cursor-pointer flex-shrink-0" @click="handleBack" />
          <span class="ml-10px text-16px truncate" :title="formData.name || '创建流程'">
            {{ formData.name || '创建流程' }}
          </span>
        </div>

        <!-- 步骤条 -->
        <div class="flex-1 flex items-center justify-center h-full">
          <div class="w-400px flex items-center justify-between h-full">
            <div
              v-for="(step, index) in steps"
              :key="index"
              class="flex items-center cursor-pointer mx-15px relative h-full"
              :class="[
                currentStep === index
                  ? 'text-[#3473ff] border-[#3473ff] border-b-2 border-b-solid'
                  : 'text-gray-500'
              ]"
              @click="handleStepClick(index)"
            >
              <div
                class="w-28px h-28px rounded-full flex items-center justify-center mr-8px border-2 border-solid text-15px"
                :class="[
                  currentStep === index
                    ? 'bg-[#3473ff] text-white border-[#3473ff]'
                    : 'border-gray-300 bg-white text-gray-500'
                ]"
              >
                {{ index + 1 }}
              </div>
              <span class="text-16px font-bold whitespace-nowrap">{{ step.title }}</span>
            </div>
          </div>
        </div>

        <!-- 右侧按钮 -->
        <div class="w-200px flex items-center justify-end gap-2">
          <el-button
            v-if="actionType === 'update'"
            type="success"
            :disabled="formLoading"
            @click="handleDeploy"
          >
            发 布
          </el-button>
          <el-button type="primary" :disabled="formLoading" @click="handleSave">
            <span v-if="actionType === 'definition'">恢 复</span>
            <span v-else>保 存</span>
          </el-button>
        </div>
      </div>

      <!-- 主体内容 -->
      <div class="mt-50px">
        <!-- 第一步：基本信息 -->
        <div v-show="currentStep === 0" class="mx-auto w-560px">
          <BasicInfo
            v-model="formData"
            :categoryList="categoryList"
            :userList="userList"
            ref="basicInfoRef"
          />
        </div>

        <!-- 第二步：表单设计 -->
        <div v-show="currentStep === 1" class="mx-auto w-560px">
          <FormDesign v-model="formData" :formList="formList" ref="formDesignRef" />
        </div>

        <!-- 第三步：流程设计 -->
        <ProcessDesign v-if="currentStep === 2" v-model="formData" ref="processDesignRef" />

        <!-- 第四步：更多设置 -->
        <div v-show="currentStep === 3" class="mx-auto w-700px">
          <ExtraSettings v-model="formData" ref="extraSettingsRef" />
        </div>
      </div>
    </div>
  </ContentWrap>
</template>

<script setup lang="ts">
import { useRoute, useRouter } from 'vue-router'
import { useMessage } from '@/hooks/web/useMessage'
import { useUserStoreWithOut } from '@/stores/modules/user'
import { useTagsView } from '@/hooks/web/useTagsView'
import { ModelApi } from '@/api/bpm/model'
import { FormApi, FormVO } from '@/api/bpm/form'
import { CategoryApi, CategoryVO } from '@/api/bpm/category'
import * as StaffApi from '@/api/system/staff'
import {
  BpmModelFormTypeEnum,
  BpmModelTypeEnum,
  BpmAutoApproveTypeEnum,
  UserSelectScopeEnum, EnableStatusEnum
} from '@/utils/constants'
import BasicInfo from './BasicInfo.vue'
import FormDesign from './FormDesign.vue'
import ProcessDesign from './ProcessDesign.vue'
import ExtraSettings from './ExtraSettings.vue'
import { ProcessDefinitionApi, ProcessDefinitionInfoVO } from '@/api/bpm/process_definition'

defineOptions({ name: 'BpmModelCreate' })

const router = useRouter()
const tagsView = useTagsView()
const route = useRoute()
const message = useMessage()
const userStore = useUserStoreWithOut()

// 组件引用
const basicInfoRef = ref<InstanceType<typeof BasicInfo> | null>()
const formDesignRef = ref<InstanceType<typeof FormDesign> | null>()
const processDesignRef = ref<InstanceType<typeof ProcessDesign> | null>()
const extraSettingsRef = ref<InstanceType<typeof ExtraSettings> | null>()

const currentStep = ref(-1) // 步骤控制。-1 一开始全部不展示等当前页面数据初始化完成

/** 步骤校验函数 */
const validateBasic = async () => {
  await basicInfoRef.value?.validate()
}

/** 表单设计校验 */
const validateForm = async () => {
  await formDesignRef.value?.validate()
}

/** 流程设计校验 */
const validateProcess = async () => {
  // await processDesignRef.value?.validate()
  if (!processData.value) {
    throw new Error('请设计流程模型')
  }
}

const steps = [
  { title: '基本信息', validator: validateBasic },
  { title: '表单设计', validator: validateForm },
  { title: '流程设计', validator: validateProcess },
  { title: '更多设置', validator: null }
]

const formLoading = ref(false) // 表单加载中标记
// 表单数据
const formData: any = ref({
  id: undefined,
  key: '',
  name: '',
  category: undefined,
  icon: undefined,
  description: '',
  type: BpmModelTypeEnum.Bpmn,
  visible: true,
  startUserType: undefined,
  startUserIds: [],
  manageUserIds: [],
  formType: BpmModelFormTypeEnum.Normal,
  formId: undefined,
  formCustomCreatePath: '',
  formCustomViewPath: '',
  allowCancelRunningProcess: true,
  processIdRule: {
    enable: false,
    prefix: '',
    infix: '',
    postfix: '',
    length: 5
  },
  autoApprovalType: BpmAutoApproveTypeEnum.None,
  titleSetting: {
    enable: false,
    title: ''
  },
  summarySetting: {
    enable: false,
    summary: []
  }
})

// 流程数据
const processData = ref<any>()

provide('processData', processData)
provide('modelData', formData)

// 数据列表
const formList = ref<FormVO[]>([])
const categoryList = ref<CategoryVO[]>([])
const userList = ref<StaffApi.StaffVO[]>([])

/** 初始化数据 */
// 场景：创建、修改、复制(新建)、恢复(更新)
const actionType = route.params.type as string
const initData = async () => {
  if (actionType === 'definition') {
    // 流程定义恢复场景
    const definitionId = route.params.id as string
    const data: ProcessDefinitionInfoVO = await ProcessDefinitionApi.getProcessDefinition(definitionId)
    data.id = data.modelId!
    delete data.modelId
    delete data.sort // 维持现在的排序值
    formData.value = data
    formData.value.startUserType =
      formData.value.startUserIds?.length > 0
        ? UserSelectScopeEnum.Selected
        : UserSelectScopeEnum.All
  } else if (['update', 'copy'].includes(actionType)) {
    // 修改、拷贝场景
    const modelId = route.params.id as string
    formData.value = await ModelApi.getModel(modelId)
    formData.value.startUserType =
      formData.value.startUserIds?.length > 0
        ? UserSelectScopeEnum.Selected
        : UserSelectScopeEnum.All
    if (actionType === 'copy') {
      formData.value.id = undefined // 移除id，以便转换为新增逻辑
      formData.value.key += '_copy'
      formData.value.name += '副本'
      tagsView.setTitle('复制流程')
    }
  } else {
    // 新增场景
    formData.value.startUserType = UserSelectScopeEnum.All // 全体用户
    formData.value.manageUserIds = [userStore.getUserId]
    formData.value.category = history.state?.category
  }
  // 获取表单列表
  formList.value = await FormApi.getFormSimpleList()
  // 获取分类列表
  categoryList.value = await CategoryApi.getCategorySimpleList(EnableStatusEnum.Enabled)
  // 获取用户列表
  userList.value = await StaffApi.getStaffSimpleList()

  // 最终，设置 currentStep 切换到第一步
  currentStep.value = 0
}

/** 根据类型切换流程数据 */
watch(
  async () => formData.value.type,
  () => {
    if (formData.value.type === BpmModelTypeEnum.Bpmn) {
      processData.value = formData.value.bpmnXml
    }
  },
  {
    immediate: true
  }
)

const validateAllSteps = async () => {
  for (let i = 0; i < steps.length; i++) {
    if (steps[i].validator) {
      try {
        await steps[i].validator!()
      } catch (e) {
        currentStep.value = i
        throw new Error(`请完善${steps[i].title}`)
      }
    }
  }
}

const handleSave = async () => {
  try {
    await validateAllSteps()

    prepareSubmit()
  } catch (error: any) {
    message.warning(error.message || '请完善所有步骤的必填信息')
  }

  formLoading.value = true
  try {
    const modelData = {
      ...formData.value
    }

    if (actionType === 'definition') {
      // 恢复 -> 更新
      await ModelApi.updateModel(modelData)
      message.success('恢复成功，可点击【发布】按钮，进行模型发布')
    } else if (actionType === 'update') {
      // 更新
      await ModelApi.updateModel(modelData)
      message.success('修改成功，可点击【发布】按钮，进行模型发布')
    } else if (actionType === 'copy') {
      // 拷贝
      formData.value.id = await ModelApi.createModel(modelData)
      message.success('复制成功，可点击【发布】按钮，进行模型发布')
    } else {
      // 新增
      formData.value.id = await ModelApi.createModel(modelData)
      message.success('新建成功，可点击【发布】按钮，进行模型发布')
    }
    if (actionType !== 'update') {
      tagsView.closeCurrent()
      await router.push({ name: 'BpmModel', state: { reload: true } })
    }
  } finally {
    formLoading.value = false
  }
}

const handleDeploy = async () => {
  // 修改场景下直接发布，新增场景下需要先确认
  if (!formData.value.id) {
    await message.confirm('是否确认发布该流程？')
  }
  try {
    // 校验所有步骤
    await validateAllSteps()

    prepareSubmit()
  } catch (error: any) {
    message.warning(error.message || '发布失败')
  }

  formLoading.value = true
  try {
    const modelData = {
      ...formData.value
    }

    if (formData.value.id) {
      await ModelApi.updateModel(modelData)
    } else {
      formData.value.id = await ModelApi.createModel(modelData)
    }

    await ModelApi.deployModel(formData.value.id)
    message.success('发布成功')
    await router.push({ name: 'BpmModel', state: { reload: true } })
  } finally {
    formLoading.value = false
  }
}

const prepareSubmit = () => {
  if (!formData.value.id) {
    // 创建操作时，同步流程key与name，更新时key与name不可变更
    syncProcessKeyAndName(formData.value.key, formData.value.name)
    if (formData.value.type === BpmModelTypeEnum.Bpmn) {
      formData.value.bpmnXml = processData.value
    }
  }
}

const handleStepClick = async (step: number) => {
  try {
    if (currentStep.value !== step) {
      const validator = steps[currentStep.value].validator
      if (validator) {
        await validator()
      }

      if (currentStep.value === 0 && !formData.value.id) {
        syncProcessKeyAndName(formData.value.key, formData.value.name)
      }
    }
    currentStep.value = step
  } catch (error) {
    message.warning('请先完善当前步骤必填信息')
  }
}

/** 返回列表页 */
const handleBack = () => {
  // 先删除当前页签
  tagsView.closeCurrent()
  // 跳转到列表页
  router.push({ name: 'BpmModel', state: { reload: true } })
}

const domParser = new DOMParser()
const xmlSerializer = new XMLSerializer()
const syncProcessKeyAndName = (id: any, name: any) => {
  if (processData.value) {
    if (formData.value.type === BpmModelTypeEnum.Bpmn) {
      const xmlDoc = domParser.parseFromString(processData.value, 'text/xml')
      let processElements = xmlDoc.getElementsByTagName('process')
      if (!processElements || processElements.length === 0) {
        processElements = xmlDoc.getElementsByTagName('bpmn2:process')
      }
      if (processElements?.length) {
        const oldId = processElements[0].getAttribute('id')
        const oldName = processElements[0].getAttribute('name')
        if (oldId != id || oldName != name) {
          processElements[0].setAttribute('id', id)
          processElements[0].setAttribute('name', name)
          processData.value = xmlSerializer.serializeToString(xmlDoc)
        }
      }
    }
  }
}

onMounted(async () => {
  await initData()
})

onBeforeUnmount(() => {
  // 清理所有引用
  basicInfoRef.value = null
  formDesignRef.value = null
  processDesignRef.value = null
  extraSettingsRef.value = null
})
</script>

<style lang="scss" scoped>
.border-bottom {
  border-bottom: 1px solid #dcdfe6;
}

.text-primary {
  color: #3473ff;
}

.bg-primary {
  background-color: #3473ff;
}

.border-primary {
  border-color: #3473ff;
}
</style>
